/*!
 * @file      apm32f10x_emmc.c
 *
 * @brief     This file provides all the EMMC firmware functions
 *
 * @version   V1.0.0
 *
 * @date      2019-8-6
 *
 */
 
#include "apm32f10x_emmc.h"
#include "apm32f10x_rcm.h"

/*!
 * @brief     Rest the EMMMC NOR/SRAM Banks registers
 *
 * @param     EMMC_Bank_NORSRAM_T:
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NORSRAMReset(EMMC_Bank_NORSRAM_T EMMC_Bank)
{
    /* EMMC_Bank1_NORSRAM1 */
    if(EMMC_Bank == EMMC_Bank1_NORSRAM1)
    {
        EMMC_Bank1->SNCTRL_T[EMMC_Bank] = 0x000030DB;
    }
    /* EMMC_Bank1_NORSRAM2,  EMMC_Bank1_NORSRAM3 or EMMC_Bank1_NORSRAM4 */
    else
    {
        EMMC_Bank1->SNCTRL_T[EMMC_Bank] = 0x000030D2;
    }
    EMMC_Bank1->SNCTRL_T[EMMC_Bank + 1] = 0x0FFFFFFF;
    EMMC_Bank1E->SNWCLK[EMMC_Bank] = 0x0FFFFFFF;
}

/*!
 * @brief     Rest the EMMMC NAND Banks registers
 *
 * @param     EMMC_Bank_NAND_T:
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NANDReset(EMMC_Bank_NAND_T EMMC_Bank)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        /* Set the EMMC_Bank2 registers to their reset values */
        EMMC_Bank2->PNCTRL2 = 0x00000018;
        EMMC_Bank2->IFSTS2 = 0x00000040;
        EMMC_Bank2->NPCT2 = 0xFCFCFCFC;
        EMMC_Bank2->NPAT2 = 0xFCFCFCFC;
    }
    /* EMMC_Bank3_NAND */
    else
    {
        /* Set the EMMC_Bank3 registers to their reset values */
        EMMC_Bank3->PNCTRL3 = 0x00000018;
        EMMC_Bank3->IFSTS3 = 0x00000040;
        EMMC_Bank3->NPCT3 = 0xFCFCFCFC;
        EMMC_Bank3->NPAT3 = 0xFCFCFCFC;
    }
}

/*!
 * @brief     Rest the EMMMC PCCARD Banks registers
 *
 * @param     None
 *
 * @retval    None
 *
 * @note
 */
void EMMC_PCCARDRest(void)
{
    /* Set the EMMC_Bank4 registers to their reset values */
    EMMC_Bank4->PNCTRL4 = 0x00000018;
    EMMC_Bank4->IFSTS4 = 0x00000000;
    EMMC_Bank4->NPCT4 = 0xFCFCFCFC;
    EMMC_Bank4->NPAT4 = 0xFCFCFCFC;
    EMMC_Bank4->PIOT4 = 0xFCFCFCFC;
}

/*!
 * @brief     Config the EMMC NOR/SRAM Banks according to the specified parameters in the EMMC_NORSRAMConfigStruct.
 *
 * @param     EMMC_NORSRAMConfig_T*
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NORSRAMConfig(EMMC_NORSRAMConfig_T* EMMC_NORSRAMConfigStruct)
{
    /* Bank1 NOR/SRAM control register configuration */
    EMMC_Bank1->SNCTRL_T[EMMC_NORSRAMConfigStruct->EMMC_Bank] =
        (uint32_t)EMMC_NORSRAMConfigStruct->EMMC_DataAddressMux |
        EMMC_NORSRAMConfigStruct->EMMC_MemoryType |
        EMMC_NORSRAMConfigStruct->EMMC_MemoryDataWidth |
        EMMC_NORSRAMConfigStruct->EMMC_BurstAcceesMode |
        EMMC_NORSRAMConfigStruct->EMMC_AsynchronousWait |
        EMMC_NORSRAMConfigStruct->EMMC_WaitSignalPolarity |
        EMMC_NORSRAMConfigStruct->EMMC_WrapMode |
        EMMC_NORSRAMConfigStruct->EMMC_WAIT_SIGNAL_ACTIVE |
        EMMC_NORSRAMConfigStruct->EMMC_WriteOperation |
        EMMC_NORSRAMConfigStruct->EMMC_WaiteSignal |
        EMMC_NORSRAMConfigStruct->EMMC_ExtendedMode |
        EMMC_NORSRAMConfigStruct->EMMC_WriteBurst;

    if(EMMC_NORSRAMConfigStruct->EMMC_MemoryType == EMMC_MEMORYTYPE_NOR)
    {
        EMMC_Bank1->SNCTRL_T[EMMC_NORSRAMConfigStruct->EMMC_Bank] |= 0x00000040;
    }

    /* Bank1 NOR/SRAM timing register configuration */
    EMMC_Bank1->SNCTRL_T[EMMC_NORSRAMConfigStruct->EMMC_Bank + 1] =
        (uint32_t)EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ADDRESS_SETUP_TIME |
        (EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ADDRESS_HOLD_TIME << 4) |
        (EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_DATA_SETUP_TIME << 8) |
        (EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_BUS_TURN_AROUND_DURATION << 16) |
        (EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_CLK_DIVISION << 20) |
        (EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_DATA_LATENCY << 24) |
        EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ACCESS_MODE;

    /* Bank1 NOR/SRAM timing register for write configuration, if extended mode is used */
    if(EMMC_NORSRAMConfigStruct->EMMC_ExtendedMode == EMMC_EXTENDEN_MODE_ENABLE)
    {
        EMMC_Bank1E->SNWCLK[EMMC_NORSRAMConfigStruct->EMMC_Bank] =
            (uint32_t)EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ADDRESS_SETUP_TIME |
            (EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ADDRESS_HOLD_TIME << 4) |
            (EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_DATA_SETUP_TIME << 8) |
            (EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_CLK_DIVISION << 20) |
            (EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_DATA_LATENCY << 24) |
            EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ACCESS_MODE;
    }
    else
    {
        EMMC_Bank1E->SNWCLK[EMMC_NORSRAMConfigStruct->EMMC_Bank] = 0x0FFFFFFF;
    }
}

/*!
 * @brief     Config the EMMC NAND Banks according to the specified parameters in the EMMC_NANDInitStruct.
 *
 * @param     EMMC_NANDConfig_T*
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NANDConfig(EMMC_NANDConfig_T* EMMC_NANDConfigStruct)
{
    uint32_t tmppcr = 0x00000000, tmppmem = 0x00000000, tmppatt = 0x00000000;

    /* Set the tmppcr value according to EMMC_NANDInitStruct parameters */
    tmppcr = (uint32_t)EMMC_NANDConfigStruct->EMMC_Waitfeature | 0x00000008 |
             EMMC_NANDConfigStruct->EMMC_MemoryDataWidth |
             EMMC_NANDConfigStruct->EMMC_ECC |
             EMMC_NANDConfigStruct->EMMC_ECCPageSize |
             (EMMC_NANDConfigStruct->EMMC_TCLRSetupTime << 9) |
             (EMMC_NANDConfigStruct->EMMC_TARSetupTime << 13);

    /* Set tmppmem value according to EMMC_CommonSpaceTimingStructure parameters */
    tmppmem = (uint32_t)EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_SetupTime |
              (EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_WaitSetupTime << 8) |
              (EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HoldSetupTime << 16) |
              (EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HiZSetupTime << 24);

    /* Set tmppatt value according to EMMC_AttributeSpaceTimingStructure parameters */
    tmppatt = (uint32_t)EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_SetupTime |
              (EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_WaitSetupTime << 8) |
              (EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HoldSetupTime << 16) |
              (EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HiZSetupTime << 24);

    if(EMMC_NANDConfigStruct->EMMC_Bank == EMMC_NAND_Bank2)
    {
        /* EMMC_Bank2_NAND registers configuration */
        EMMC_Bank2->PNCTRL2 = tmppcr;
        EMMC_Bank2->NPCT2 = tmppmem;
        EMMC_Bank2->NPAT2 = tmppatt;
    }
    else
    {
        /* EMMC_Bank3_NAND registers configuration */
        EMMC_Bank3->PNCTRL3 = tmppcr;
        EMMC_Bank3->NPCT3 = tmppmem;
        EMMC_Bank3->NPAT3 = tmppatt;
    }

}

/*!
 * @brief     Config the EMMC NAND PCCARD according to the specified parameters in the EMMC_PCCARInitStruct.
 *
 * @param     EMMC_NANDConfig_T*
 *
 * @retval    None
 *
 * @note
 */
void EMMC_PCCARDConfig(EMMC_PCCARDConfig_T* EMMC_PCCARDConfigStruct)
{
    /* Set the PCR4 register value according to EMMC_PCCARDInitStruct parameters */
    EMMC_Bank4->PNCTRL4 = (uint32_t)EMMC_PCCARDConfigStruct->EMMC_Waitfeature | EMMC_MEMORY_DATA_WIDTH_16b |
                          (EMMC_PCCARDConfigStruct->EMMC_TCLRSetupTime << 9) |
                          (EMMC_PCCARDConfigStruct->EMMC_TARSetupTime << 13);

    /* Set PMEM4 register value according to EMMC_CommonSpaceTimingStructure parameters */
    EMMC_Bank4->NPCT4 = (uint32_t)EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_SetupTime |
                        (EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_WaitSetupTime << 8) |
                        (EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HoldSetupTime << 16) |
                        (EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HiZSetupTime << 24);

    /* Set PATT4 register value according to EMMC_AttributeSpaceTimingStructure parameters */
    EMMC_Bank4->NPAT4 = (uint32_t)EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_SetupTime |
                        (EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_WaitSetupTime << 8) |
                        (EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HoldSetupTime << 16) |
                        (EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HiZSetupTime << 24);

    /* Set PIO4 register value according to EMMC_IOSpaceTimingStructure parameters */
    EMMC_Bank4->PIOT4 = (uint32_t)EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_SetupTime |
                        (EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_WaitSetupTime << 8) |
                        (EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_HoldSetupTime << 16) |
                        (EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_HiZSetupTime << 24);
}

/*!
 * @brief     Fills each EMMC_NORSRAMInitStruct member with its default value.
 *
 * @param     EMMC_NORSRAMConfig_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NORSRAMStructConfig(EMMC_NORSRAMConfig_T* EMMC_NORSRAMConfigStruct)
{
    /* Reset NOR/SRAM Init structure parameters values */
    EMMC_NORSRAMConfigStruct->EMMC_Bank = EMMC_Bank1_NORSRAM1;
    EMMC_NORSRAMConfigStruct->EMMC_DataAddressMux = EMMC_DataAddressMux_Enable;
    EMMC_NORSRAMConfigStruct->EMMC_MemoryType = EMMC_MEMORYTYPE_SRAM;
    EMMC_NORSRAMConfigStruct->EMMC_MemoryDataWidth = EMMC_MEMORY_DATA_WIDTH_8b;
    EMMC_NORSRAMConfigStruct->EMMC_BurstAcceesMode = EMMC_BURST_ACCESS_MODE_DISABLE;
    EMMC_NORSRAMConfigStruct->EMMC_AsynchronousWait = EMMC_ASYNCHRONOUSWAIT_DISABLE;
    EMMC_NORSRAMConfigStruct->EMMC_WaitSignalPolarity = EMMC_WAIT_SIGNAL_POLARITY_LOW;
    EMMC_NORSRAMConfigStruct->EMMC_WrapMode = EMMC_WRAP_MODE_DISABLE;
    EMMC_NORSRAMConfigStruct->EMMC_WAIT_SIGNAL_ACTIVE = EMMC_WAIT_SIGNAL_ACTIVE_BEFOREWAITSTATE;
    EMMC_NORSRAMConfigStruct->EMMC_WriteOperation = EMMC_WRITE_OPERATION_ENABLE;
    EMMC_NORSRAMConfigStruct->EMMC_WaiteSignal = EMMC_WAITE_SIGNAL_ENABLE;
    EMMC_NORSRAMConfigStruct->EMMC_ExtendedMode = EMMC_EXTENDEN_MODE_DISABLE;
    EMMC_NORSRAMConfigStruct->EMMC_WriteBurst = EMMC_WRITE_BURST_DISABLE;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ADDRESS_SETUP_TIME = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ADDRESS_HOLD_TIME = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_DATA_SETUP_TIME = 0xFF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_BUS_TURN_AROUND_DURATION = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_CLK_DIVISION = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_DATA_LATENCY = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_ReadWriteTimingStruct->EMMC_ACCESS_MODE = EMMC_Access_Mode_A;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ADDRESS_SETUP_TIME = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ADDRESS_HOLD_TIME = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_DATA_SETUP_TIME = 0xFF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_BUS_TURN_AROUND_DURATION = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_CLK_DIVISION = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_DATA_LATENCY = 0xF;
    EMMC_NORSRAMConfigStruct->EMMC_WriteTimingStruct->EMMC_ACCESS_MODE = EMMC_Access_Mode_A;
}

/*!
* @brief     Fills each EMMC_NANDInitStruct member with its default value.
*
* @param     EMMC_NORSRAMConfig_T
*
* @retval    None
*
* @note
*/
void NANDStructConfig(EMMC_NANDConfig_T* EMMC_NANDConfigStruct)
{
    /* Reset NAND Init structure parameters values */
    EMMC_NANDConfigStruct->EMMC_Bank = EMMC_NAND_Bank2;
    EMMC_NANDConfigStruct->EMMC_Waitfeature = EMMC_WAIT_FEATURE_DISABLE;
    EMMC_NANDConfigStruct->EMMC_MemoryDataWidth = EMMC_MEMORY_DATA_WIDTH_8b;
    EMMC_NANDConfigStruct->EMMC_ECC = EMMC_ECC_DISABLE;
    EMMC_NANDConfigStruct->EMMC_ECCPageSize = EMMC_ECC_PAGE_SIZE_256Bytes;
    EMMC_NANDConfigStruct->EMMC_TCLRSetupTime = 0x0;
    EMMC_NANDConfigStruct->EMMC_TARSetupTime = 0x0;
    EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_SetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_WaitSetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HoldSetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HiZSetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_SetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_WaitSetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HoldSetupTime = 0xFC;
    EMMC_NANDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HiZSetupTime = 0xFC;
}

/*!
 * @brief     Fills each EMMC_PCCARDInitStruct member with its default value.
 *
 * @param     EMMC_PCCARDConfig_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_PCCARDStructConfig(EMMC_PCCARDConfig_T* EMMC_PCCARDConfigStruct)
{
    /* Reset PCCARD Init structure parameters values */
    EMMC_PCCARDConfigStruct->EMMC_Waitfeature = EMMC_WAIT_FEATURE_DISABLE;
    EMMC_PCCARDConfigStruct->EMMC_TCLRSetupTime = 0x0;
    EMMC_PCCARDConfigStruct->EMMC_TARSetupTime = 0x0;
    EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_SetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_WaitSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HoldSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_CommonSpaceTiming_T->EMMC_HiZSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_SetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_WaitSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HoldSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_AttributeSpaceTiming_T->EMMC_HiZSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_SetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_WaitSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_HoldSetupTime = 0xFC;
    EMMC_PCCARDConfigStruct->EMMC_IOSpaceTiming_T->EMMC_HiZSetupTime = 0xFC;
}

/*!
 * @brief     Enables or disables the specified NOR/SRAM Memory Bank.
 *
 * @param     EMMC_Bank_NORSRAM_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NORSRAMEnable(EMMC_Bank_NORSRAM_T EMMC_Bank)
{
    EMMC_Bank1->SNCTRL_T[EMMC_Bank] |= 0x00000001;
}

/*!
* @brief     Disbles or disables the specified NOR/SRAM Memory Bank.
*
* @param     EMMC_Bank_NORSRAM_T
*
* @retval    None
*
* @note
*/
void EMMC_NORSRAMDisable(EMMC_Bank_NORSRAM_T EMMC_Bank)
{
    EMMC_Bank1->SNCTRL_T[EMMC_Bank] &= 0x000FFFFE;
}

/*!
 * @brief     Enables or disables the specified NAND Memory Bank.
 *
 * @param     EMMC_Bank_NAND_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NANDEnable(EMMC_Bank_NAND_T EMMC_Bank)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->PNCTRL2 |= 0x00000004;
    }
    else
    {
        EMMC_Bank3->PNCTRL3 |= 0x00000004;
    }
}

/*!
* @brief     Disbles or disables the specified NAND Memory Bank.
*
* @param     EMMC_Bank_NAND_T
*
* @retval    None
*
* @note
*/
void EMMC_NANDDisable(EMMC_Bank_NAND_T EMMC_Bank)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->PNCTRL2 &= 0x000FFFFB;
    }
    else
    {
        EMMC_Bank3->PNCTRL3 &= 0x000FFFFB;
    }
}

/*!
 * @brief     Enbles or disables the EMMC NAND ECC feature.
 *
 * @param     EMMC_Bank_NAND_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NANDECCEnable(EMMC_Bank_NAND_T EMMC_Bank)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->PNCTRL2 |= 0x00000040;
    }
    else
    {
        EMMC_Bank3->PNCTRL3 |= 0x00000040;
    }
}

/*!
 * @brief     Disbles or disables the EMMC NAND ECC feature.
 *
 * @param     EMMC_Bank_NAND_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_NANDECCDisable(EMMC_Bank_NAND_T EMMC_Bank)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->PNCTRL2 &= 0x000FFFBF;
    }
    else
    {
        EMMC_Bank3->PNCTRL3 &= 0x000FFFBF;
    }
}

/*!
 * @brief     Read the error correction code register value.
 *
 * @param     EMMC_Bank_NAND_T
 *
 * @retval    None
 *
 * @note
 */
uint32_t  EMMC_ReadECC(EMMC_Bank_NAND_T EMMC_Bank)
{
    uint32_t eccval = 0x00000000;

    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        eccval = EMMC_Bank2->ECC2;
    }
    else
    {
        eccval = EMMC_Bank3->ECC3;
    }
    return eccval;
}

/*!
 * @brief     Enables the specified EMMC interrupts.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_INT_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_IntEnable(EMMC_Bank_NAND_T EMMC_Bank, EMMC_INT_T EMMC_Int)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->IFSTS2 |= EMMC_Int;
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        EMMC_Bank3->IFSTS3 |= EMMC_Int;
    }
    else
    {
        EMMC_Bank4->IFSTS4 |= EMMC_Int;
    }
}

/*!
 * @brief     Enables the specified EMMC interrupts.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_INT_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_IntDisable(EMMC_Bank_NAND_T EMMC_Bank, EMMC_INT_T EMMC_Int)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->IFSTS2 &= ~EMMC_Int;
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        EMMC_Bank3->IFSTS3 &= ~EMMC_Int;
    }
    else
    {
        EMMC_Bank4->IFSTS4 &= ~EMMC_Int;
    }
}

/*!
 * @brief     Read the specified EMMC flag is set or not.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_FLAG_T
 *
 * @retval    SET or RESET
 *
 * @note
 */
uint16_t EMMC_ReadFlagStatus(EMMC_Bank_NAND_T EMMC_Bank, EMMC_FLAG_T EMMC_flag)
{
    uint32_t tmpsr = 0x00000000;

    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        tmpsr = EMMC_Bank2->IFSTS2;
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        tmpsr = EMMC_Bank3->IFSTS3;
    }
    else
    {
        tmpsr = EMMC_Bank4->IFSTS4;
    }
    /* Get the flag status */
    if((tmpsr & EMMC_flag) != RESET)
    {
        return SET;
    }
    else
    {
        return RESET;
    }
}

/*!
 * @brief     Clears the EMMC's pending flags.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_FLAG_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_ClearFlag(EMMC_Bank_NAND_T EMMC_Bank, EMMC_FLAG_T EMMC_flag)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->IFSTS2 &= ~EMMC_flag;
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        EMMC_Bank3->IFSTS3 &= ~EMMC_flag;
    }
    else
    {
        EMMC_Bank4->IFSTS4 &= ~EMMC_flag;
    }
}

/*!
 * @brief     Read the specified EMMC interrupt has occurred or not.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_INT_T
 *
 * @retval    SET or RESET
 *
 * @note
 */
uint16_t  EMMC_ReadIntFlag(EMMC_Bank_NAND_T EMMC_Bank, EMMC_INT_T EMMC_Int)
{
    uint32_t tmpsr = 0x0, itstatus = 0x0, itenable = 0x0;

    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        tmpsr = EMMC_Bank2->IFSTS2;
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        tmpsr = EMMC_Bank3->IFSTS3;
    }
    else
    {
        tmpsr = EMMC_Bank4->IFSTS4;
    }

    itstatus = tmpsr & EMMC_Int;
    itenable = tmpsr & (EMMC_Int >> 3);

    if((itstatus != RESET) && (itenable != RESET))
    {
        return SET;
    }
    else
    {
        return RESET;
    }
}

/*!
 * @brief     Clears the EMMC's interrupt Flag.
 *
 * @param     EMMC_Bank_NAND_T  EMMC_INT_T
 *
 * @retval    None
 *
 * @note
 */
void EMMC_ClearIntFlag(EMMC_Bank_NAND_T EMMC_Bank, EMMC_INT_T EMMC_Int)
{
    if(EMMC_Bank == EMMC_Bank2_NAND)
    {
        EMMC_Bank2->IFSTS2 &= ~(EMMC_Int >> 3);
    }
    else if(EMMC_Bank == EMMC_Bank3_NAND)
    {
        EMMC_Bank3->IFSTS3 &= ~(EMMC_Int >> 3);
    }
    else
    {
        EMMC_Bank4->IFSTS4 &= ~(EMMC_Int >> 3);
    }
}
